﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;

namespace EssentialWF.Activities
{
    [Serializable]
    public class PrioritizedInterleave : CompositeActivity
    {
        //private IList<PriorityWriteLine> sorted = null;
        private static int currentIndex = int.MinValue;
        //private int childCount = 0;

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            if (EnabledActivities.Count == 0)
            {
                return ActivityExecutionStatus.Closed;
            }

            int minPriority = GetPriority(EnabledActivities, int.MaxValue, int.MinValue);
            ExecuteChild(executionContext, minPriority);

            //currentIndex = GetPriority(EnabledActivities, int.MaxValue, int.MinValue);
            //ExecuteChild(executionContext, currentIndex);

            return ActivityExecutionStatus.Executing;
        }

        void ContinueAt(object sender, ActivityExecutionStatusChangedEventArgs e)
        {
            e.Activity.Closed -= this.ContinueAt;

            ActivityExecutionContext aec =
                sender as ActivityExecutionContext;

            int priority = ((PriorityWriteLine)e.Activity).Priority;
            bool allSamePriorityChildAreClosed = true;
            bool allChildAreColosed = true;

            foreach (PriorityWriteLine child in EnabledActivities)
            {
                // Console.WriteLine(child.Text + "'s status is " + child.ExecutionStatus.ToString());
                if (child.ExecutionStatus != ActivityExecutionStatus.Closed)
                {
                    allChildAreColosed = false;
                }

                if (child.Priority == priority
                    && child.ExecutionStatus != ActivityExecutionStatus.Closed)
                {
                    allSamePriorityChildAreClosed = false;
                }
            }

            if (allChildAreColosed == true)
            {
                aec.CloseActivity();
                return;
            }

            if (priority == currentIndex)
            {
                return;
            }
            else
            {
                currentIndex = priority;
            }

            if (allSamePriorityChildAreClosed == true)
            {
                //Console.WriteLine("1 Priority is " + priority);
                priority = GetPriority(EnabledActivities, int.MaxValue, priority);
                //Console.WriteLine("2 Priority is " + priority);
                ExecuteChild(aec, priority);


            }
        }

        void ExecuteChild(ActivityExecutionContext context, int priority)
        {

            foreach (PriorityWriteLine child in EnabledActivities)
            {
                if (child.Priority == priority)
                {
                    child.Closed += this.ContinueAt;
                    context.ExecuteActivity(child);
                }
            }
        }

        int GetPriority(ReadOnlyCollection<Activity> list, int maxLimit, int minLimit)
        {
            int result = maxLimit;
            foreach (PriorityWriteLine obj in list)
            {
                if (result > obj.Priority && obj.Priority > minLimit)
                {
                    result = obj.Priority;
                }
            }

            return result;
        }
    }
}
